/**
 * This file defines the character creation screen
 */
package edu.gatech.spacetraderteam3.view;

import java.awt.Color;
import java.awt.Graphics2D;

import edu.gatech.spacetraderteam3.controller.GUIEventHandler;
import edu.gatech.spacetraderteam3.model.GameState;
import edu.gatech.spacetraderteam3.model.Player;
import edu.gatech.spacetraderteam3.model.Game.Difficulty;

/**
 * The Main Menu GUI
 * Displays the Main Menu GUI and allows the user to navigate to a Character
 * Creation GUI when a new game is selected
 * 
 * @author Alex Ikonomidis and Ashutosh Gupta
 * @version 1.0
 */
public class ViewSystemCharacterCreation extends ViewSystem {

    /**
     * The Character Creation Window
     */
    private final SGGWindow creationWindow;

    /**
     * A Label that indicates the username field
     */
    private SGGLabel labelUsername;

    /**
     * A Label that shows the max skill points
     */
    private SGGLabel labelMaxSkillPoints;

    /**
     * A Label that shows the amount of skill points used
     */
    private SGGLabel labelUsedSkillPoints;

    /**
     * A Label that indicates the difficulty field
     */
    private SGGLabel labelDifficulty;

    /**
     * A Drop Down Box to choose the difficulty
     */
    private SGGDropDownBox<Difficulty> dropBoxDifficulty;

    /**
     * The Text Field to enter the new Username
     */
    private SGGTextField textFieldUsername;

    /**
     * The 4 skill sliders that allocate skill points
     */
    private SGGSlider skillSliders[];

    /**
     * The maximum number of points set for skill allocation and a sum
     */
    private int maxPoints, sum;

    /**
     * Window size constant
     */
    private static final int WINDOW_SIZE = 505;

    /**
     * Numeric Constant
     */
    private static final int P_TWO = 2;

    /**
     * Numeric Constant
     */
    private static final int P_THREE = 3;

    /**
     * Numeric Constant
     */
    private static final int P_FIFTEEN = 15;

    /**
     * Numeric Constant
     */
    private static final int P_SIXTEEN = 16;

    /**
     * Numeric Constant
     */
    private static final int P_FORTY = 40;

    /**
     * Numeric Constant
     */
    private static final int P_FIFTY = 50;

    /**
     * Numeric Constant
     */
    private static final int P_HUNDRED = 100;

    /**
     * Numeric Constant
     */
    private static final int P_TWO_HUNDRED = 200;

    /**
     * Numeric Constant
     */
    private static final int P_THREE_HUNDRED = 300;

    /**
     * Numeric Constant
     */
    private static final int P_FOUR_HUNDRED = 400;

    /**
     * Numeric Constant
     */
    private static final int P_EIGHTYFIVE = 85;

    /**
     * Numeric Constant
     */
    private static final int P_TWO_SEVENTY = 270;

    /**
     * Numeric Constant
     */
    private static final int P_THREE_SEVENTY = 370;

    /**
     * Numeric Constant
     */
    private static final int P_ONE_SEVENTY = 170;

    /**
     * Numeric Constant
     */
    private static final int P_FOUR_TWENTYFIVE = 425;

    /**
     * Numeric Constant
     */
    private static final int P_ONE_FORTYFIVE = 145;

    /**
     * Numeric Constant
     */
    private static final int P_FOUR_OFIVE = 405;

    /**
     * Numeric Constant
     */
    private static final int P_ONE_SIXTY = 160;

    /**
     * Numeric Constant
     */
    private static final int P_THREE_SIXTY = 360;

    /**
     * Instantiates the Main Menu along with it's two Windows (the Title & the Character
     * Create)
     * and their respective SGGComponents
     */
    public ViewSystemCharacterCreation() {
        creationWindow = getCharacterCreationWindow();
        drawBackground();
    }

    /**
     * Invokes non-final methods that draw the background
     */
    private final void drawBackground() {
        setStarVelocity(-1, 0);
        drawPlanets(true);
    }

    /**
     * Creates and returns a new character-creation window
     * This window holds all components (textfields, sliders, buttons, etc)
     * that are used to create a new player
     * 
     * @return a character creation window
     */
    private final SGGWindow getCharacterCreationWindow() {
        maxPoints = Player.INITIAL_SKILL_POINTS;

        final SGGWindow window = new SGGWindow(0, 0, WINDOW_SIZE, WINDOW_SIZE,
                GameState.CHARACTER_CREATION);
        window.setAlignment(SGGWindow.Alignment.CENTER);

        labelUsername = new SGGLabel("Enter Username:");
        labelUsername.setColor(Color.white);
        window.add(labelUsername, P_FIFTY, P_FIFTY);

        textFieldUsername = new SGGTextField("");
        textFieldUsername.setColor(Color.white);
        window.add(textFieldUsername, P_THREE_HUNDRED, P_FIFTY);

        labelMaxSkillPoints = new SGGLabel("Skill Points: " + maxPoints);
        labelMaxSkillPoints.setColor(Color.white);
        window.add(labelMaxSkillPoints, P_FIFTY, P_HUNDRED);

        labelUsedSkillPoints = new SGGLabel("Assigned Skill Points: 00");
        labelUsedSkillPoints.setColor(Color.white);
        window.add(labelUsedSkillPoints, P_THREE_HUNDRED, P_HUNDRED);

        final String[] skills = Player.SKILLS;
        skillSliders = new SGGSlider[skills.length];

        for (int i = 0; i < skills.length; i++) {
            SGGLabel label = new SGGLabel(skills[i]);
            label.setColor(Color.white);
            window.add(label, P_EIGHTYFIVE + P_HUNDRED * i, P_ONE_FORTYFIVE);

            skillSliders[i] = new SGGSlider(P_TWO_HUNDRED, true, 0, P_SIXTEEN, 0);
            window.add(skillSliders[i], P_EIGHTYFIVE + P_HUNDRED * i, P_ONE_SEVENTY);
        }

        labelDifficulty = new SGGLabel("Choose Difficulty:");
        labelDifficulty.setColor(Color.white);
        window.add(labelDifficulty, P_FORTY, P_FOUR_OFIVE);

        dropBoxDifficulty = new SGGDropDownBox<Difficulty>(Difficulty.values(), P_TWO);
        dropBoxDifficulty.setColor(Color.GREEN);
        window.add(dropBoxDifficulty, P_ONE_SIXTY, P_FOUR_HUNDRED);

        SGGButton button = new SGGButton("ACCEPT");
        button.setSGGEventListener(new CharacterCreationListener());
        window.add(button, P_THREE_SIXTY, P_FOUR_TWENTYFIVE);
        button = new SGGButton("BACK");
        button.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.backToTitle();
            }
        });
        window.add(button, P_FIFTY, P_FOUR_TWENTYFIVE);
        return window;
    }

    /**
     * Paints the GUI of the Main Menu
     * 
     * @param g
     *            : the Graphics2D object used to paint components
     */
    public void paint(Graphics2D g) {
        super.paint(g);
        final int increment = skillSliders[0].getHeight() / maxPoints;
        final int bottom = skillSliders[0].getY() + skillSliders[0].getHeight();
        final int right = skillSliders[P_THREE].getX() + skillSliders[P_THREE].getWidth();
        final int min = bottom - increment * maxPoints;
        creationWindow.paint(g);
        g.setColor(Color.white);
        final int x = creationWindow.getX();
        final int y = creationWindow.getY();
        g.drawString("16", x + P_FIFTY, y + P_ONE_SEVENTY);
        g.drawLine(x + P_FIFTY, bottom - increment * maxPoints, right, bottom - increment
                * maxPoints);
        g.drawString("08", x + P_FIFTY, y + P_TWO_SEVENTY);
        g.drawLine(x + P_FIFTY, bottom - ((increment * maxPoints) >> 1), right, bottom
                - ((increment * maxPoints) >> 1));

        g.drawString("00", x + P_FIFTY, y + P_THREE_SEVENTY);
        g.drawLine(x + P_FIFTY, bottom, x + P_FOUR_HUNDRED, bottom);

        sum = 0;
        for (int i = 0; i < skillSliders.length; i++) {
            sum += skillSliders[i].getValue();
        }

        textFieldUsername
                .setColor(textFieldUsername.getText().trim().equals("") ? Color.RED
                        : Color.GREEN);

        final Color col = (sum > maxPoints ? Color.RED : sum < maxPoints ? Color.BLUE
                : Color.GREEN);
        g.setColor(col);
        labelUsedSkillPoints.setColor(col);
        labelUsedSkillPoints.setText("Assigned Skill Points: " + sum);
        g.drawString("Total Skill", right + P_FIFTEEN,
                     Math.max(min, bottom - sum * increment));
        g.drawLine(x + P_FIFTY, Math.max(min, bottom - sum * increment), right,
                   Math.max(min, bottom - sum * increment));
    }

    /**
     * Resets the values for the window to default selections
     */
    public void reset() {
        dropBoxDifficulty.setValue(P_TWO);
        textFieldUsername.setText("");
        for (SGGSlider s : skillSliders) {
            s.setValue(P_THREE);
        }
    }

    /**
     * This class's toString method
     * 
     * @return the string representation of the class
     */
    public String toString() {
        return super.toString();
    }

    /**
     * Private inner class that listens to events generated by the ACCEPT button
     * in the Character Creation GUI
     * 
     * @author Alexander Ikonomidis
     */
    private class CharacterCreationListener implements SGGEventListener {
        /**
         * Checks to make sure that the appropriate data is entered into the Character
         * Creation GUI. If the data fits the game requirements, then the GUIEventHandler
         * is notified and given the entered data.
         * 
         * @param sgge
         *            : the event generated by the ACCEPT button
         */
        public void doEvent(SGGEvent sgge) {
            if (sum == maxPoints && !textFieldUsername.getText().trim().equals("")) {
                final int[] skills = new int[skillSliders.length];
                for (int i = 0; i < skillSliders.length; i++) {
                    skills[i] = skillSliders[i].getValue();
                }
                GUIEventHandler.createCharacter(textFieldUsername.getText().trim(),
                                                skills, dropBoxDifficulty.getValue());
            }
        }

        /**
         * This class's toString method
         * 
         * @return the string representation of the class
         */
        public String toString() {
            return super.toString();
        }
    }
}